import React from 'react';
import {Badge, ImagePicker, List, Modal, Toast, WhiteSpace} from 'antd-mobile';
import styles from './index.less';
import {btnSound, playSound} from '@/utils/sounds-res';
import SocketEvent from '@/service/event';
import {log} from '@/utils/log-utils';
import ChildTitleLayout from "@/header/child";
import AdvancedBtn from "@/button";
import {CACHE_BATTLE_KEY} from "@/utils/cache-key-utils";
import AdvancedSpin from "@/spinner";

/**
 * 模式枚举
 * @type {string}
 */
// 匹配模式
export const MODE_RANDOM_PK = 'MODE_RANDOM_BATTLE';
// 开房模式
export const MODE_FREEDOM_PK = 'MODE_FREEDOM_BATTLE'
// 观战
export const MODE_WATCH = 'MODE_WATCH';
// 复盘
export const MODE_REVIEW = 'MODE_REVIEW';

class Platform extends React.Component {

  constructor(props) {
    super(props);

    this.viewModeDefault = 'viewModeDefault';
    this.viewModeJoinRoom = 'viewModeJoinRoom';
    this.viewModeUserDetail = 'viewModeUserDetail';

    this.state = {
      text: '',
      loading: false,
      user: null,
      onlineCount: 0,
      battleCount: 0,
      viewMode: this.viewModeDefault,
    };

    this.onlineCountRespId = 'platformOnlineCountId';

    this.unRegisterServices = [];
    this.unRegisterServices.push(this.onlineCountRespId);
  }

  componentDidMount() {
    const cacheUserDetail = sessionStorage.getItem(CACHE_BATTLE_KEY);
    if (cacheUserDetail) {
      const user = JSON.parse(cacheUserDetail);
      this.setState({ user });
    }
    // 页面显/隐的事件
    document.addEventListener('visibilitychange', this.sendOnlineCount);
    // 查询用户详情(更新上面的缓存)
    this.queryUserDetail();
    // 启动事件监听
    this.startAllEventListen();
    // 进入页面时请求一次数据
    this.sendOnlineCount(false);
  }

  /**
   * 查询用户详情
   */
  queryUserDetail = () => {
    // 查询用户信息(此处如果后端强制恢复对局，会导致一个内存泄露的warn)
    SocketEvent.emit(this.props.socket, 'userDetailApi', {
      userId: this.props.userId,
    }, resp => {
      log("用户详情：", resp);
      if (resp.code === 'success') {
        const {user} = resp.data;
        this.setState({ user });
        sessionStorage.setItem(CACHE_BATTLE_KEY, JSON.stringify(user));
      } else {
        Toast.show('账号信息异常，请重新登录');
        this.props.goBack();
      }
    });
  }

  /**
   * 请求在线数据
   */
  sendOnlineCount = (hidden) => {
    const isHidden = (typeof hidden === 'boolean') ? hidden : document.hidden;
    if(!isHidden) {
      SocketEvent.emit(this.props.socket, 'onlineCountApi', {
        userId: this.props.userId,
      }, resp => {
        log("请求统计在线数据返回：", resp);
      });
    }
  }

  /**
   * 事件监听
   */
  startAllEventListen = () => {
    // 在线数据统计
    SocketEvent.register('onlineCountRespApi', this.onlineCountRespId, resp => {
      if(resp.code === 'success') {
        log("在线数据统计：", resp);
        const { action, onlineCount, battleCount } = resp.data;

        // 全量数据
        if(action === 'update') {
          this.setState({ onlineCount, battleCount });
          // 增量数据
        } else if(action === 'add') {
          const oldOnlineCount = this.state.onlineCount;
          const oldBattleCount = this.state.battleCount;

          this.setState({
            onlineCount: oldOnlineCount + onlineCount,
            battleCount: oldBattleCount + battleCount,
          });
        }
      }
    });

  }

  componentWillUnmount() {
    document.removeEventListener('visibilitychange', this.sendOnlineCount);
    SocketEvent.unRegister(this.unRegisterServices);
  }

  /**
   * 返回上一页（带提示）
   */
  goBack = e => {
    playSound(btnSound);
    Modal.alert('系统提示', '确认退出吗?', [
      {text: '取消', onPress: () => playSound(btnSound)},
      {
        text: '确认', onPress: () => {
          playSound(btnSound);
          SocketEvent.emit(this.props.socket, 'loginOutApi', {
            userId: this.props.userId,
          }, resp => {
            log('退出登录resp:', resp);
            this.props.goBack();
          });
        },
      },
    ]);
  };

  /**
   * 进入匹配页面
   */
  handleMatchMode = (e, mode) => {
    playSound(btnSound);
    // FIXME 目前只开放对战模块
    if(mode !== MODE_RANDOM_PK && mode !== MODE_WATCH) {
      Toast.show('功能研发中')
    } else {
      this.props.selectComplete(mode);
    }
  };

  /**
   * 修改用户名称
   */
  updateUserName = () => {
    playSound(btnSound);
    const { user } = this.state;
    const tips = <div style={{ fontSize: '13px', color: '#bbb' }}>名称长度不超过五个字</div>;
    Modal.prompt('请输入新昵称', tips, [
      {text: '取消', onPress: () => playSound(btnSound)},
      {
        text: '修改', onPress: value => {
          playSound(btnSound);
          if (value.length === 0 || value.length > 5) {
            Toast.fail('昵称无效');
          } else {
            const { userId, socket} = this.props;
            SocketEvent.emit(socket, 'modifyUserDetailApi', {
              userId: userId,
              modifyDetail: {
                userName: value,
              }
            }, resp => {
              if (resp.code === 'success') {
                Toast.show('修改成功');
                user.userName = value;
                this.setState({ user });
                sessionStorage.removeItem(CACHE_BATTLE_KEY);
              } else {
                // 修改失败等提示
                Toast.show(resp.msg);
              }
            })
          }
        },
      },
    ]);
  }

  /**
   * 修改头像
   * @param files 文件列表
   * @param oprType 操作类型 add/remove
   * @param index 移除时的索引值
   */
  updateIconUrl = (files, oprType, index) => {

    if(files.length > 0) {
      // 获取第一个文件对象
      const [ fileObj ] = files;
      const { file, url } = fileObj;

      if(file.size >= 1e6) {
        Toast.show('文件过大(限制1M)');
        return;
      }

      this.setState({ loading: true, text: '头像上传中'});
      const { userId, socket} = this.props;
      const { user } = this.state;
      SocketEvent.emit(socket, 'uploadPictureApi', {
        userId: userId,
        fileName: file.name,
        base64: url,
        contentType: file.type,
        fileSize: file.size
      }, resp => {
        log('上传头像返回：', resp);
        // 文件上传成功后，开始更新数据
        if (resp.code === 'success') {
          const { fileId } = resp.data;
          SocketEvent.emit(socket, 'modifyUserDetailApi', {
            userId: userId,
            modifyDetail: {
              iconUrl: fileId,
            }
          }, resp => {
            this.setState({ loading: false });
            if (resp.code === 'success') {
              Toast.show('上传成功');
              user.iconUrl = url;
              this.setState({ user });
              sessionStorage.removeItem(CACHE_BATTLE_KEY);
            } else {
              // 修改失败等提示
              Toast.show(resp.msg);
            }
          })
        } else {
          // 修改失败等提示
          Toast.show(resp.msg);
          this.setState({ loading: false });
        }
      })
    }
  }

  /**
   * 平台界面
   * @return {JSX.Element}
   */
  platformView = () => {
    const {user, onlineCount, battleCount} = this.state;

    return (
      <div className={styles.platformBody}>
        <div className={styles.user}>
          <div className={styles.icon}
               onClick={e => {
                playSound(btnSound);
                this.setState({ viewMode: this.viewModeUserDetail })
               }}>
            <div className={styles.imgWrap}>
              <img src={user?.iconUrl || require('@/assets/images/user.png')} width='100%' height='100%' />
            </div>
            <div className={styles.battle}>
              <div className={styles.title}>
                <div className={styles.name}>
                  <div>{user?.userName}</div>
                </div>
                <div className={styles.sort}>
                  <div>排名：<span>{user?.scoreSort ? `第 ${user.scoreSort} 位` : ' - '}</span></div>
                </div>
              </div>

              <div className={styles.info}>
                <div className={styles.subject}>
                  <div>积分</div>
                  <div>
                    <span>胜</span>&nbsp;
                    <span>负</span>&nbsp;
                    <span>和</span>
                  </div>
                </div>

                <div className={styles.value}>
                  <div>{user?.score || '-'}</div>
                  <div>
                    <span>{user?.pkWinCount || '0'}</span>/
                    <span>{user?.pkFailCount || '0'}</span>/
                    <span>{user?.pkPeaceCount || '0'}</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div className={styles.platform}>
          <Badge text={`在线: ${onlineCount}`} className={styles.badge}>
            <div className={styles.btnRed} onClick={e => {
              playSound(btnSound);
              this.setState({
                viewMode: this.viewModeJoinRoom
              })
            }} >加入房间</div>
          </Badge>
          <Badge text={`场次: ${battleCount}`} className={styles.badge}>
            <div className={styles.btnRed} onClick={e => this.handleMatchMode(e, MODE_WATCH)} >观战对局</div>
          </Badge>
          <Badge text={`场次: ${user?.pkTotalCount}`} className={styles.badge}>
            <div className={styles.btnRed} onClick={e => this.handleMatchMode(e, MODE_REVIEW)} >复盘对局</div>
          </Badge>
        </div>
      </div>
    );
  }

  /**
   * 房间模式选择界面
   * @return {{}}
   */
  joinRoomSelectView = () => {
    return (
      <div className={styles.joinRoomSelectBody}>
        <ChildTitleLayout text={'房间模式'} />

        <div className={styles.content}>
          <AdvancedBtn type={'normal'} text="匹配对战" onClick={e => this.handleMatchMode(e, MODE_RANDOM_PK)} />
          <h1 />
          <AdvancedBtn type={'normal'} text="开房约战" onClick={e => this.handleMatchMode(e, MODE_FREEDOM_PK)} />
        </div>
      </div>
    );
  }

  /**
   * 个人中心
   */
  userDetailView = () => {
    const { user } = this.state;
    return (
      <div className={styles.userDetail}>
        <div className={styles.head}>
          <div className={styles.userIcon} onClick={e => { playSound(btnSound); this.queryUserDetail();} }>
            <img src={user?.iconUrl || require('@/assets/images/user.png')} width='100%' height='100%'/>
            <ImagePicker
              className={styles.imgPicker}
              style={{opacity: 0}}
              length="1"
              onFail={msg => Toast.show(msg)}
              onChange={this.updateIconUrl}
              disableDelete
              accept="image/gif,image/jpeg,image/jpg,image/png"
            />
          </div>
          <div className={styles.close}
               onClick={e => {
                 playSound(btnSound);
                 this.setState({viewMode: this.viewModeDefault})
               }}>
            <div title={'close'}/>
          </div>
        </div>
        <WhiteSpace />
        <List>
          <List.Item extra={user?.userId} arrow="horizontal">账号</List.Item>
          <List.Item onClick={this.updateUserName} extra={user?.userName} arrow="horizontal">昵称</List.Item>
          <List.Item
            arrow="horizontal"
            onClick={e => {
              playSound(btnSound);
              Toast.show('排行榜未开放')
            }}
            extra={<div className={styles.score}>{user?.score}</div>}
          >积分</List.Item>
          <List.Item
            arrow="horizontal"
            onClick={e => {
              playSound(btnSound);
              Toast.show('功能未开放')
            }}
            extra={<div className={styles.battle}>
              <span>{user?.pkWinCount || '0'}</span>/
              <span>{user?.pkFailCount || '0'}</span>/
              <span>{user?.pkPeaceCount || '0'}</span>
            </div>}
          >战绩</List.Item>
          <List.Item arrow="horizontal" onClick={e => Toast.show('功能未开放')}>游戏规则</List.Item>
        </List>
        <WhiteSpace />
        <List>
          <List.Item arrow="horizontal" onClick={e => this.goBack(e)}>切换账号</List.Item>
          <List.Item arrow="horizontal" onClick={e => Toast.show('功能未开放')}>设置</List.Item>
        </List>
      </div>
    );
  }

  render() {
    const { viewMode } = this.state;
    return (
      <div className={styles.wrap}>
        {viewMode === this.viewModeDefault && this.platformView()}
        {viewMode === this.viewModeJoinRoom && this.joinRoomSelectView()}
        {viewMode === this.viewModeUserDetail && this.userDetailView()}
        <AdvancedSpin text={this.state.text} show={this.state.loading}/>
      </div>
    );
  }
}


export default Platform;
